package com.letoken.platform.repo.generator;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.Entity;
import com.baomidou.mybatisplus.generator.config.builder.Mapper;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author <a href="https://www.fengwenyi.com">Erwin Feng</a>
 * @since 2021-09-26
 */
@Log4j2
@Component
public class MyAutoGenerator {


    /**
     * 执行生成代码
     * @param tableName 需生成的表表名
     * @param packageName 生成实体所属包
     * @param moduleName  controller、service所处的工程名
     * @param entityModule 实体类、mapper所属工程名
     * @param isController 是否需要controller
     */

    public void execute(String tableName, String packageName, String moduleName, String entityModule, boolean isController) {

        this.resource = entityModule + File.separator + CodeGeneratorConfig.RESOURCES_DIR + File.separator + "mapper" + File.separator + packageName;
//        handleDb(username, password, dbUrl);
//        handleTable(tableName, bo);
        try {
//            controller、service
            new MyAutoGenerator(username, password, dbUrl, split(tableName), moduleName, this.entityModule,
                    this.resource, isController, this.serverPackage).execute();

            //实体类
            new MyAutoGenerator(username, password, dbUrl, split(tableName), entityModule, this.entityModule,
                    this.resource, isController, this.modlePackage + "." + packageName).execute1();
        } catch (Exception e) {
            String errMsg = ExceptionUtils.getStackTrace(e);
            log.error(errMsg);
        }
    }



    String username = "root";
    String password = "20a3c5daa9e03dcce2fa";
    String dbUrl = "jdbc:mysql://54.254.30.62:15232/sss?useUnicode=true&characterEncoding=utf8&useSSL=false";
    String[] tableNames;
    String moduleName = "";
    String entityModule = "";
    String resource = "";
    String modlePackage = "com.letoken.platform.repo";
    String serverPackage = "com.letoken.platform.app";
    String packageName = "";
    boolean isController = true;

    public MyAutoGenerator() {

    }

    public MyAutoGenerator(String username, String password, String dbUrl, String[] tableNames, String moduleName,
                           String entityModule, String resource, boolean isController, String packageName) {
        this.username = username;
        this.password = password;
        this.dbUrl = dbUrl;
        this.tableNames = tableNames;
        this.moduleName = moduleName;
//        this.entityModule = entityModule;
        this.resource = resource;
        this.isController = isController;
        this.packageName = packageName;

    }

    public void execute() {
        FastAutoGenerator fastAutoGenerator = FastAutoGenerator.create(dataSourceBuilder());
        fastAutoGenerator.globalConfig(this::globalConfigBuilder)
                .strategyConfig(this::strategyConfigBuilder);
        fastAutoGenerator.packageConfig(this::packageConfigBuilder);
        if (this.isController) {
            fastAutoGenerator.templateConfig(this::templateConfigNoEntity);
        } else {
            fastAutoGenerator.templateConfig(this::templateConfigNoController);
        }
        fastAutoGenerator.execute();
    }

    public void execute1() {
        FastAutoGenerator fastAutoGenerator = FastAutoGenerator.create(dataSourceBuilder());
        fastAutoGenerator.globalConfig(this::globalConfigBuilder)
                .strategyConfig(this::strategyConfigBuilder);
        fastAutoGenerator.packageConfig(this::packageConfigBuilder1);
        fastAutoGenerator.templateConfig(this::templateConfigOnlyEntity);
        fastAutoGenerator.execute();
    }

    private String[] split(String value) {
        if (!StringUtils.hasText(value)) {
            return new String[]{};
        }
        List<String> valueList = new ArrayList<>();
        String[] values;
        if (value.contains(",")) {
            values = value.split(",");
        } else if (value.contains("\n")) {
            values = value.split("\n");
        } else {
            values = value.split(" ");
        }
        for (String str : values) {
            str = str.trim();
            if (StringUtils.hasText(str)) {
                valueList.add(str);
            }
        }
        String[] result = new String[valueList.size()];
        return valueList.toArray(result);
    }

    public DataSourceConfig.Builder dataSourceBuilder() {
        return new DataSourceConfig.Builder(dbUrl, username, password);
    }

    public void globalConfigBuilder(GlobalConfig.Builder builder) {

//        builder.fileOverride().author(bo.getAuthor());

        String outDir = CodeGeneratorConfig.OUTPUT_DIR + File.separator + this.moduleName + CodeGeneratorConfig.MAIN_DIR;
//        if (StringUtils.hasText(bo.getOutDir())) {
//            outDir = bo.getOutDir();
//        }
        builder.outputDir(outDir);
        DateType dateType = DateType.TIME_PACK;
//        if (!"8".equalsIgnoreCase(bo.getJdkVersion())) {
//            dateType = DateType.ONLY_DATE;
//        }
        builder.dateType(dateType);

        if (BooleanUtils.isTrue(true)) {
            builder.enableSwagger();
        }

    }

    public void packageConfigBuilder(PackageConfig.Builder builder) {
        builder
                //文件输出包名
                .parent(packageName)
                // builder.moduleName("");
                .controller(CodeGeneratorConfig.PACKAGE_NAME_CONTROLLER)
                .service(CodeGeneratorConfig.PACKAGE_NAME_SERVICE)
                .serviceImpl(CodeGeneratorConfig.PACKAGE_NAME_SERVICE_IMPL);
    }

    public void packageConfigBuilder1(PackageConfig.Builder builder) {
        HashMap<OutputFile, String> map = new HashMap<OutputFile, String>(1);
        map.put(OutputFile.mapperXml, this.resource);
        builder
                //文件输出包名
                .parent(packageName)
                // builder.moduleName("");
                .entity(CodeGeneratorConfig.PACKAGE_NAME_MODEL)
                .mapper(CodeGeneratorConfig.PACKAGE_NAME_DAO)
                .xml(CodeGeneratorConfig.DIR_NAME_XML).pathInfo(map);
    }

    public void strategyConfigBuilder(StrategyConfig.Builder builder) {
        builder.addInclude(tableNames)
//                .addFieldPrefix(bo.getFieldPrefixes())
//                .addTablePrefix(bo.getTablePrefixes())
//                .addExclude(bo.getExcludeTableNames())
                .entityBuilder()
                .naming(NamingStrategy.underline_to_camel)
                //.enableChainModel()
                .enableLombok()
                .enableActiveRecord()
                .formatFileName(CodeGeneratorConfig.FILE_NAME_MODEL)
                .idType(IdType.ASSIGN_ID)
//                .logicDeleteColumnName(bo.getFieldLogicDelete())
//                .versionColumnName(bo.getFieldVersion())
//                .superClass(bo.getSuperClassName())
//                .addIgnoreColumns(bo.getIgnoreColumns())
                .mapperBuilder()
                .formatMapperFileName(CodeGeneratorConfig.FILE_NAME_DAO)
                .formatXmlFileName(CodeGeneratorConfig.FILE_NAME_XML)
                .serviceBuilder()
                .formatServiceFileName(CodeGeneratorConfig.FILE_NAME_SERVICE)
                .formatServiceImplFileName(CodeGeneratorConfig.FILE_NAME_SERVICE_IMPL)
                .controllerBuilder()
                .enableRestStyle()
                .enableHyphenStyle();

        Entity.Builder entityBuilder = builder.entityBuilder();
        if (BooleanUtils.isTrue(false)) {
            entityBuilder.enableChainModel();
        }
        if (BooleanUtils.isTrue(true)) {
            entityBuilder.enableLombok();
        }
        if (BooleanUtils.isTrue(false)) {
            entityBuilder.enableColumnConstant();
        }
        // 字段注解
        if (BooleanUtils.isTrue(true)) {
            entityBuilder.enableTableFieldAnnotation();
        }

        Mapper.Builder mapperBuilder = builder.mapperBuilder();
        if (BooleanUtils.isTrue(true)) {
            mapperBuilder.enableBaseResultMap();
        }
        if (BooleanUtils.isTrue(true)) {
            mapperBuilder.enableBaseColumnList();
        }

        // 开启mapper注解
        if (BooleanUtils.isTrue(false)) {
            mapperBuilder.enableMapperAnnotation();
        }
    }


    public void templateConfigNoEntity(TemplateConfig.Builder builder) {
        builder.mapper(null).mapperXml(null).disable(TemplateType.ENTITY).build();
    }

    public void templateConfigOnlyEntity(TemplateConfig.Builder builder) {
        builder.controller(null).service(null).serviceImpl(null).build();
    }

    public void templateConfigNoController(TemplateConfig.Builder builder) {
        builder.mapper(null).mapperXml(null).disable(TemplateType.ENTITY).disable(TemplateType.CONTROLLER).build();
    }

}
